#include "TrueText/Config.h"
#include "FontImpl.h"
#include FT_GLYPH_H
#include FT_SIZES_H
#include FT_CACHE_H
#include "FaceImpl.h"
#include "ftutils.h"
#include "ftcache.h"

#include "TrueText/FontEffectOutline.h"
#include "TrueText/FontEffectShadow.h"

namespace TrueText {

FontImpl::FontImpl(boost::shared_ptr<FaceImpl> face, float height)
    : face(face)
    , height(height)
    , ftsize(0)
{
    rebuildFtSize();
}

FontImpl::FontImpl(const FontImpl& rhs)
    : face(rhs.face)
    , height(rhs.height)
    , ftsize(0)
	, color(rhs.color)
	, outline(rhs.outline)
	, shadow(rhs.shadow)
{
    rebuildFtSize();
}

const FontImpl& FontImpl::operator=(const FontImpl& rhs)
{
    if (this == &rhs)
        return *this;

    face = rhs.face;
    height = rhs.height;
    ftsize = 0;
	color = rhs.color;
	outline = rhs.outline;
	shadow = rhs.shadow;

    rebuildFtSize();

    return *this;
}

FontImpl::~FontImpl()
{
	cleanupFtSize();
}

void FontImpl::SetHeight(float value)
{
    height = value;
	rebuildFtSize();
}

void FontImpl::cleanupFtSize()
{
	// No need to delete size since FreeType cache does this for us
	if (ftsize)
		ftsize = 0;
}

FTC_ScalerRec FontImpl::getScaler()
{
	FTC_ScalerRec sr;
	sr.face_id = reinterpret_cast<FTC_FaceID>(face->getFaceId());
	sr.width = 0;
	sr.height = static_cast<FT_F26Dot6>(height * (1 << 6));
	sr.pixel = 0;
	sr.x_res = DPI_Horizontal;
	sr.y_res = DPI_Vertical;

	return sr;
}

void FontImpl::rebuildFtSize()
{
	cleanupFtSize();

	FTC_ScalerRec sr = getScaler();
    FT_EH(FTC_Manager_LookupSize(GetFtcManager(), &sr, &this->ftsize));
}

FT_Size FontImpl::getSize() 
{
	rebuildFtSize();
	return this->ftsize;
}

FaceId* FontImpl::getFaceId()
{
	return this->face->getFaceId();
}

float FontImpl::GetLineHeight() const
{
	return
		static_cast<float>(GetHeight()) // Font size in points
		* 72.0f // Amount of points in an inch
		/ static_cast<float>(DPI_Vertical);
}

const Color& FontImpl::GetColor() const
{
	return color;
}

void FontImpl::SetColor(const Color& value)
{
	color = value;
}

FontEffectOutline& FontImpl::Outline()
{
	return outline;
}

FontEffectShadow& FontImpl::Shadow()
{
	return shadow;
}


}